/**
 * Created by waterworld on 16-5-19.
 */
let fileUtil = module.exports;
let fs = require('fs');
let P = require('bluebird');
let mkdirp = require('mkdirp');
let utilCount = 0;
let maxFileSize = 1024 * 1024 * 20;//20m
let checkCount = 10000;
let filesMap = {};
let defaultPath = './private/database/record/';
let xml2js = require('xml2js');
let http = require('http');
let https = require('https');
let path = require('path');
path.resolve(__dirname, '..');
let pfs = P.promisifyAll(fs);
let os = require('os');
let request = require("request")
let FormData = require('form-data');

fileUtil.getLocalIP = function () {
    let map = [];
    let ifaces = os.networkInterfaces();
    console.log(ifaces);
    for (let dev in ifaces) {
        let tokens = dev.split(':');
        let dev2 = null;
        if (tokens.length == 2) {
            dev2 = 'eth1:' + tokens[1];
        } else if (tokens.length == 1) {
            dev2 = 'eth1';
        }
        if (null == ifaces[dev2]) {
            //continue;
        }
        // 找到eth0和eth1分别的ip
        let ip = null, ip2 = null;
        ifaces[dev].forEach(function (details) {
            if (details.family == 'IPv4') {
                ip = details.address;
            }
        });

        if (null == ip) {
            continue;
        }
        // 将记录添加到map中去
        if (ip.indexOf('10.') == 0 ||
            ip.indexOf('172.') == 0 ||
            ip.indexOf('192.') == 0) {
            map.push({ "intranet_ip": ip });
        } else {
            map.push({ "internet_ip": ip });
        }

    }
    return map;
};


fileUtil.GetRandomNum = function (Min, Max) {
    let Range = Max - Min;
    let Rand = Math.random();
    return (Min + Math.round(Rand * Range));
};

fileUtil.checkDir = function (dir, cb) {
    fs.exists(dir, function (exists) {
        if (exists) {
            cb(true);
        } else {
            fs.mkdir(dir, function (err) {
                if (!err) {
                    //console.log("操作成功！");
                    cb(true);
                } else {
                    //console.log("操作失败！");
                    cb(false);
                }
            });
        }
    });
};

fileUtil.mkdirAsync = P.promisify(mkdirp.mkdirp);
fileUtil.mkdir = mkdirp.mkdirp;

fileUtil.appendLog = function (txt) {

};

fileUtil.getDateNow = function () {
    let myDate = new Date();
    let sdate = myDate.getFullYear().toString() + '-' + (myDate.getMonth() + 1) + '-' + myDate.getDate() + '-' + myDate.getHours() + '-' + myDate.getMinutes() + '-' + myDate.getSeconds();
    return sdate;
};


function writeFile(file, str) {
    // 测试用的中文
    // appendFile，如果文件不存在，会自动创建新文件
    // 如果用writeFile，那么会删除旧文件，直接写新文件
    try {
        fs.appendFile(file, str, function (err) {
            if (err)
                console.log("写入文件 failed " + err);
        });
    }
    catch (e) {
        console.log('writeFile error', e);
    }
}

let writePer15Minute = function (str) {
    let t = new Date();
    let year = t.getFullYear();
    let mon = t.getMonth() + 1; if (mon < 10) mon = '0' + mon;
    let date = t.getDate(); if (date < 10) date = '0' + date;
    let hour = t.getHours(); if (hour < 10) hour = '0' + hour;
    let minute = t.getMinutes(); if (minute < 10) minute = '0' + minute;
    let second = t.getSeconds(); if (second < 10) second = '0' + second;
    let ms = Math.floor((t.getTime() % 10000) / 10);
    let m = Math.floor(minute / 15);
    //D:\adev\zjhServer\web-server\lib\util\fileUtil.js
    let file = __dirname + '/../../../alog/gameZjh/' + year + '-' + mon + '-' + date + ' ' + hour + '-' + m + '.txt';
    //writeFile(file,str+'\r\n');
};

let writePer15Minute0 = function (dir, str) {
    let t = new Date();
    let year = t.getFullYear();
    let mon = t.getMonth() + 1; if (mon < 10) mon = '0' + mon;
    let date = t.getDate(); if (date < 10) date = '0' + date;
    let hour = t.getHours(); if (hour < 10) hour = '0' + hour;
    let minute = t.getMinutes(); if (minute < 10) minute = '0' + minute;
    let second = t.getSeconds(); if (second < 10) second = '0' + second;
    let ms = Math.floor((t.getTime() % 10000) / 10);
    let m = Math.floor(minute / 15);
    //D:\adev\zjhServer\web-server\lib\util\fileUtil.js
    let file = __dirname + '/../../../alog/' + dir + '/' + year + '-' + mon + '-' + date + ' ' + hour + '-' + m + '.txt';
    //writeFile(file,str+'\r\n');
};

fileUtil.writePer15mAsync = P.coroutine(function* (str) {
    let t = new Date();
    let year = t.getFullYear();
    let mon = t.getMonth() + 1;
    if (mon < 10) mon = '0' + mon;
    let date = t.getDate();
    if (date < 10) date = '0' + date;
    let hour = t.getHours();
    if (hour < 10) hour = '0' + hour;
    let minute = t.getMinutes();
    if (minute < 10) minute = '0' + minute;
    let second = t.getSeconds();
    if (second < 10) second = '0' + second;
    let ms = Math.floor((t.getTime() % 10000) / 10);
    let m = Math.floor(minute / 15);
    let file = __dirname + '/../log/' + year + '-' + mon + '-' + date + '_' + hour + '-' + m + '.txt';
    str += '\r\n';
    yield pfs.appendFileAsync(file, str);
});

console.logg = function () {
    let s = '[' + getDateTime() + ']';
    let info = '';
    let len = arguments.length;
    for (let i = 0; i < len; i++) {
        let s1 = arguments[i];
        if (typeof s1 == 'object') s1 = JSON.stringify(s1);
        info = info + s1 + ' ';
    }
    console.log(s, info);
    writePer15Minute(s + info);
};

function getCaller() {
    let stack = getStack();

    // Remove superfluous function calls on stack
    stack.shift(); // getCaller --> getStack
    stack.shift(); // omfg --> getCaller

    let st = stack[0];
    // Return caller's caller
    return st.getFileName() + ":" + st.getLineNumber();
}

function getStack() {
    // Save original Error.prepareStackTrace
    let origPrepareStackTrace = Error.prepareStackTrace;

    // Override with function that just returns `stack`
    Error.prepareStackTrace = function (_, stack) {
        return stack;
    };

    // Create a new `Error`, which automatically gets `stack`
    let err = new Error();

    // Evaluate `err.stack`, which calls our new `Error.prepareStackTrace`
    let stack = err.stack;

    // Restore original `Error.prepareStackTrace`
    Error.prepareStackTrace = origPrepareStackTrace;

    // Remove superfluous function call on stack
    stack.shift(); // getStack --> Error

    return stack;
}

let log = console.log;
console.logw = function () {
    let caller = getCaller();
    let idx = caller.lastIndexOf("/");
    if (idx !== -1) {
        // only get short name of file
        caller = caller.substring(idx + 1);
    }

    let s = '[' + caller + ']';
    let info = '';
    let len = arguments.length;
    for (let i = 0; i < len; i++) {
        let s1 = arguments[i];
        if (typeof s1 === 'object' && s1 !== null) {
            try {
                s1 = JSON.stringify(s1);
            } catch (e) { }
        }

        info = info + s1 + ' ';
    }
    console.log(getDateTime(), s, info);

    if (console.logList) {
        let len2 = console.logList.length;
        if (len2 > 50000) console.logList.shift();
        let s2 = getDateTime() + " " + s + " " + info;
        console.logList.push(s2);
    }
};

// console.logw=function()
// {
//     let s='['+getDateTime()+']';
//     let info='';
//     let len=arguments.length;
//     for(let i=0;i<len;i++)
//     {
//         let s1=arguments[i];
//         if(typeof s1=='object') s1=JSON.stringify(s1);
//         info=info+s1+' ';
//     }
//     console.log(s,info);
//     let len=console.logList.length;
//     if(len>50000)  console.logList.shift();
//     let s1=s+info;
//     console.logList.push(s1);
//     //writePer15Minute0('web',s+info);
// }

console.logd = function () {
    let s = '[' + getDateTime() + ']';
    let info = '';
    let len = arguments.length;
    for (let i = 0; i < len; i++) {
        let s1 = arguments[i];
        if (typeof s1 == 'object') s1 = JSON.stringify(s1);
        info = info + s1 + ' ';
    }
    console.log(s, info);
    len = console.logList.length;
    if (len > 50000) console.logList.shift();
    let s1 = s + info;
    console.logList.push(s1);
    //writePer15Minute0('db',s+info);
};

function getDateTime() {
    let t = new Date();
    let year = t.getFullYear();
    let mon = t.getMonth() + 1; if (mon < 10) mon = '0' + mon;
    let date = t.getDate(); if (date < 10) date = '0' + date;
    let hour = t.getHours(); if (hour < 10) hour = '0' + hour;
    let minute = t.getMinutes(); if (minute < 10) minute = '0' + minute;
    let second = t.getSeconds(); if (second < 10) second = '0' + second;
    let ms = Math.floor((t.getTime() % 10000) / 10);
    let s = year + '-' + mon + '-' + date + ' ' + hour + ':' + minute + ':' + second + '.' + ms;
    return s;
}

fileUtil.newLog = P.coroutine(function* (name, path, maxSize) {
    let size = maxFileSize;
    if (maxSize) {
        size = maxSize;
    }
    let path0 = defaultPath;
    let suffix = '';
    if (name.indexOf('.txt') < 0) { suffix = '.txt'; }
    if (!!path) { path0 = path; }

    let obj = null;
    try {
        if (!filesMap[name]) {
            filesMap[name] = {};
            let fileItem = filesMap[name];
            fileItem.path = path0;
            fileItem.name = name;
            fileItem.suffix = suffix;
            let filePath = path0 + name + suffix;
            fileItem.fd = yield fs.openAsync(filePath, 'a');
            let fd = fileItem.fd;
            let stat = yield fs.fstatAsync(fd);
            let myDate = new Date();
            let sdate = myDate.getFullYear() + "-" + myDate.getMonth() + "-" + myDate.getDay() + "-" + myDate.getHours() + "-" + myDate.getMinutes() + "-" + myDate.getSeconds();
            let newPath = path0 + name + sdate + suffix;
            if (stat.size > size)  //文件大小超过限制，重命名
            {
                yield fs.closeAsync(fd);
                yield fs.rename(filePath, newPath);
                console.log('rename file ' + filePath);
                fileItem.fd = yield fs.openAsync(filePath, 'a');
            }
            fileItem.recordCount = 0;
            fileItem.appendLog = appendLog;
            fileItem.filePath = filePath;
            fileItem.maxSize = size;
            fileItem.close = fs.closeAsync;

            return fileItem;
        }
    }
    catch (e) {
        return null;
    }

});

fileUtil.getLogger = P.coroutine(function* (name) {
    let fileItem = filesMap[name];
    if (!fileItem) {
        fileItem = yield this.fileItem.newLog(name, defaultPath);
    }
    return fileItem;
});

//[2010-01-17 11:43:37.987] [DEBUG]
let appendLog = P.coroutine(function* (msg, obj) {
    if (this.recordCount == undefined || this.fd == undefined)
        return;
    let fd = this.fd;
    let myDate = new Date();
    let sdate = myDate.getFullYear() + "-" + myDate.getMonth() + "-" + myDate.getDay() + "-" + myDate.getHours() + "-" + myDate.getMinutes() + "-" + myDate.getSeconds();

    if (this.recordCount > checkCount) {
        let stat = yield fs.fstatAsync(fd);
        if (stat.size > this.maxSize) {//文件大小超过限制，重命名
            yield fs.closeAsync(fd);
            let newPath = this.path + this.name + sdate + this.suffix;
            yield fs.renameAsync(this.filePath, newPath);
            console.log('rename file ' + this.filePath);
            this.fd = yield fs.openAsync(this.filePath, 'a');
            this.recordCount = 0;
        }
    }
    this.recordCount++;
    sdate = '[' + fileUtil.getDateNow() + ']';
    let content = sdate + ' [' + msg + ']' + ' ' + JSON.stringify(obj) + '\r\n';
    yield fs.writeAsync(this.fd, content, 0);

});

function objTest(txt) {
    console.log(txt + 'obj ' + this.num);
}

fileUtil.test = function () {
    utilCount++;
    console.log('utilCount ' + utilCount);
};

fileUtil.getDay = function (tick) {
    let date = new Date();
    date.setTime(tick);
    let today = date;
    today.setHours(0); today.setMinutes(0); today.setSeconds(0); today.setMilliseconds(0);
    return today;
};

fileUtil.tick2DateStr = function (tick) {
    let t = new Date();
    t.setTime(tick);
    let y = t.getFullYear();
    let m = t.getMonth() + 1;
    m = (m < 10 ? "0" + m : m);
    let d = t.getDate();
    d = (d < 10 ? "0" + d : d);
    let h = t.getHours();
    h = (h < 10 ? "0" + h : h);
    let minu = t.getMinutes();
    minu = (minu < 10 ? "0" + minu : minu);
    let s = t.getSeconds();
    s = (s < 10 ? "0" + s : s);
    let str = y.toString() + "-" + m.toString() + "-" + d + "  " + h + ":" + minu + ":" + s;
    return str;
};

fileUtil.tick2DateNum = function (tick) {
    let t = new Date();
    t.setTime(tick);
    let y = t.getFullYear();
    let m = t.getMonth() + 1;
    m = (m < 10 ? "0" + m : m);
    let d = t.getDate();
    d = (d < 10 ? "0" + d : d);
    let h = t.getHours();
    h = (h < 10 ? "0" + h : h);
    let minu = t.getMinutes();
    minu = (minu < 10 ? "0" + minu : minu);
    let s = t.getSeconds();
    s = (s < 10 ? "0" + s : s);
    let str = y.toString() + m.toString() + d + h + minu + s;
    return str;
};

fileUtil.tick2DayStr = function (tick) {
    let t = new Date();
    t.setTime(tick);
    let y = t.getFullYear();
    let m = t.getMonth() + 1;
    m = (m < 10 ? "0" + m : m);
    let d = t.getDate();
    d = (d < 10 ? "0" + d : d);
    let str = y.toString() + "-" + m.toString() + "-" + d;
    return str;
};


//https://api.mch.weixin.qq.com/pay/unifiedorder
/*let options = {
    host: 'api.mch.weixin.qq.com',
    port: '443',
    path: '/pay/unifiedorder',
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': s.length
    }
};*/


fileUtil.httpPost = function (url, postData, cb) {
    let data = postData;
    if (typeof data == "object") {
        //data=JSON.stringify(data)
    }
    console.log("http post ", url, data);
    request({
        url: url,
        method: "POST",
        json: true,
        headers: {
            "content-type": "application/json",

        },
        body: data
    }, function (error, response, body) {
        if (!error) {
            if (cb) {
                cb(body);
            }
        } else {
            console.logg("httpPost 失败");
            cb(null);
        }
    });
};

//http://www.guaguadata.com:7000/sdk/action
fileUtil.httpPostFormData = function (url, postData, cb) {
    let form = new FormData();
    for (let k in postData) {
        form.append(k, postData[k]);
    }

    let headers = form.getHeaders();//这个不能少
    // headers.Cookie = cookie;//自己的headers属性在这里追加

    let request = http.request({
        method: 'post',
        url: url,
        path: '/active/post_data',
        headers: headers
    }, function (res) {
        let str = '';
        res.on('data', function (buffer) {
            str += buffer;//用字符串拼接
        }
        );
        res.on('end', () => {
            let result = JSON.parse(str);
            //上传之后result就是返回的结果
        });
    });
    form.pipe(request);
};

//http://localhost:81/guagua_demo/test.php
fileUtil.post2GgPay = function (url, postData, cb) {
    request.post({ url: 'http://localhost:3013/active/post_data', formData: postData }, function optionalCallback(err, httpResponse, body) {
        if (err) {
            return console.error('upload failed:', err);
        }
        console.log('Upload successful!  Server responded with:', body);
    });
};


fileUtil.httpRequest = function (op, postData, cb) {
    request({
        url: op.url,
        method: "POST",
        headers: op.header,
        body: postData
    }, function (error, response, body) {
        if (!error && response.statusCode === 200) {
            console.log(body); // 请求成功的处理逻辑
            if (cb) {
                cb(null, body);
            }
        }
        //console.log(body) // 请求成功的处理逻辑
    });
};

fileUtil.httpPostWrite = function (options, postData, cb) {
    let post_req = http.request(options, function (response) {
        let responseText = [];
        let size = 0;
        response.on('data', function (data) {
            responseText.push(data);
            size += data.length;
        });
        response.on('end', function () {
            // Buffer 是node.js 自带的库，直接使用
            responseText = Buffer.concat(responseText, size).toString('utf8');
            console.logg("response data ", responseText);
            cb(responseText);
        });
        response.on('error', function (e) {
            console.logg("post error ", e.message);
        });
    });

    // post the data
    console.logg("send data ", postData);
    post_req.write(postData);
    post_req.end();

    post_req.on('error', function (e) {
        console.error("error:" + e);
        return "系统异常：" + e.message;

    });
};

fileUtil.httpPostByOption = function (options, postData, cb) {
    let post_req = http.request(options, function (response) {
        let responseText = [];
        let size = 0;
        response.on('data', function (data) {
            //response.setEncoding('utf8');
            responseText.push(data);
            size += data.length;
        });
        response.on('end', function () {
            // Buffer 是node.js 自带的库，直接使用
            responseText = Buffer.concat(responseText, size).toString('utf8');
            cb(responseText);
        });
        response.on('error', function (e) {
            console.logg("post error ", e.message);
        });
    });

    // post the data
    post_req.write(postData);
    post_req.end();
};

fileUtil.httpsPost = function (options, postData, cb) {
    let post_req = https.request(options, function (response) {
        let responseText = [];
        let size = 0;
        response.on('data', function (data) {
            responseText.push(data);
            size += data.length;
        });
        response.on('end', function () {
            // Buffer 是node.js 自带的库，直接使用
            responseText = Buffer.concat(responseText, size).toString('utf8');
            cb(responseText);
        });
        response.on('error', function (e) {
            console.logg("post error ", e.message);
        });
    });

    // post the data
    post_req.write(postData);
    post_req.end();
};


exports.formatToWechatTime = function () {
    let str = new Date();
    let year = str.getFullYear();
    let month = ('0' + (str.getMonth() + 1)).substr(-2);
    let date = ('0' + str.getDate()).substr(-2);
    return year + month + date;
};

exports.toQueryString = function (obj) {
    return Object.keys(obj).filter(function (key) {
        return obj[key] !== undefined && obj[key] !== '';
    }).sort().map(function (key) {
        return key + '=' + obj[key];
    }).join('&');
};

exports.generateNonceStr = function (length) {
    let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let maxPos = chars.length;
    let noceStr = '';
    for (let i = 0; i < (length || 32); i++) {
        noceStr += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return noceStr;
};

exports.randomCode = function (length) {
    let chars = '0123456789';
    let maxPos = chars.length;
    let noceStr = '';
    for (let i = 0; i < (length || 32); i++) {
        noceStr += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return noceStr;
};

exports.buildXML = function (obj) {
    let builder = new xml2js.Builder({
        allowSurrogateChars: true
    });
    return builder.buildObject({ xml: obj });
};

exports.parseXML = function (xml, callback) {
    xml2js.parseString(xml, {
        trim: true,
        explicitArray: false
    }, function (err, result) {
        err ? callback(err) : callback(null, result ? result.xml : {});
    });
};

console.log('load fileUtil');